"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MainService = void 0;
const di_1 = require("./di");
const main_id_1 = require("./main.id");
const descriptor_1 = require("./descriptor");
class MainService {
    constructor(service) {
        this.service = service;
        this.proxy = new Map();
        this.service.set(main_id_1.IMain, this);
    }
    invoke(fn) {
        const accessor = {
            get: (id) => {
                const sd = this.createAndCacheServiceProxy(id);
                if (!sd) {
                    throw new Error(`[invokeFunction] unknown service '${id}'`);
                }
                return sd;
            },
        };
        return fn(accessor);
    }
    createAndCacheServiceProxy(id) {
        if (this.proxy.has(id)) {
            return this.proxy.get(id);
        }
        if (!this.service.has(id)) {
            return;
        }
        const proxy_index = { id };
        const proxy = new Proxy(proxy_index, {
            get: (target, prop) => {
                if (prop in target) {
                    return target[prop];
                }
                if (!target.inst) {
                    this.createInstance(target);
                }
                const r = target.inst[prop];
                if (typeof r === 'function') {
                    return r.bind(target.inst);
                }
                return r;
            },
        });
        this.proxy.set(id, proxy);
        return proxy;
    }
    createInstance(proxy) {
        const sd = this.service.get(proxy.id);
        const next_args = sd.args.slice();
        if (sd instanceof descriptor_1.Descriptor) {
            for (const dep of di_1.DI.getDep(sd.ctor)) {
                next_args[dep.index] = this.createAndCacheServiceProxy(dep.id);
            }
        }
        proxy.inst = new sd.ctor(...next_args);
    }
}
exports.MainService = MainService;
